package com.hy.main.demo.tree;

import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author yang DongYong
 * @Date 2022/4/17 - 04 - 17 - 19:16
 * @Description: com.hy.main.demo
 * @version: 1.0
 */
public class Recursion {

    /**
     * 简单递归Demo
     *
     * @param start 开始参数
     * @param end 结束参数
     * @return
     */
    public static Integer recursionSum(Integer start, Integer end) {
        // 递归方法出口
        if (start == end) {
            return end;
        }
        /**
         *  此处方法调用一共为三次
         *  方法内递归调用次数为两次
         *  第一次调用 1 ,3
         *  第二次递归调用 2 ,3
         *  第三次递归调用传入 3 ,3 此时条件成立，第三次调用方法方法开始返回3，随后则是 2 + 3返回5 回到第一次方法调用，
         *  此时方法内参数为 1 + 5 ，则1至3的和为6
         *  start的值一定时要不断变化的并且递归要具有方法出口，两者条件无一成立很容易造成死循环最终导致方法栈溢出
         */
        return start + recursionSum(start + 1, end);
    }

    public static void main(String[] args) {
        System.out.println(recursionSum(1, 3));
    }
}


@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class Menu {

    /**
     * id
     */
    public Integer id;
    /**
     * 名称
     */
    public String name;
    /**
     * 父id ，根节点为0
     */
    public Integer parentId;
    /**
     * 子节点信息
     */
    public List<Menu> childList;


    public Menu(Integer id, String name, Integer parentId) {
        this.id = id;
        this.name = name;
        this.parentId = parentId;
    }
}

class TestRecursion{
    // 模拟多级数据
    public static void main(String[] args) {
        recursions(5);

        System.out.println(factorial(5));
        // 模拟数据
        List<Menu> menus = Arrays.asList(
                new Menu(1, "新手专区", 0),
                new Menu(2, "指南", 1),
                new Menu(3, "礼包", 1),
                new Menu(4, "角色装备", 2),
                new Menu(5, "角色咨询", 2),
                new Menu(6, "角色详情", 2),
                new Menu(7, "服装礼包", 3),
                new Menu(8, "装备礼包", 3),
                new Menu(9, "金币礼包", 3)
        );
//    获取父节点的id
        List<Menu> collect = menus.stream().filter(e -> e.getParentId() == 0).map(m -> {
            m.setChildList(child(m, menus));
            return m;
        }).collect(Collectors.toList());
        System.out.println(JSON.toJSON(collect));


    }
    //递归查询子节点

    /**
     * 递归
     * 第一次调用传入父节点的值和所有查询出的值
     * @param root 父节点数据
     * @param all 所有数据
     * @return 返回子节点
     */
    public static List<Menu> child(Menu root, List<Menu> all) {
      return all.stream().filter(e-> Objects.equals(e.getParentId(),root.getId())).map(m -> {
             m.setChildList(child(m,all));
             return m;
        }).collect(Collectors.toList());
    }

    /*
        阶乘递归 每次先调用方法不会去计算* data 只有进入if之后开始返回方法值 这个时候开始计算阶乘的值
     */
    public static int  factorial(int data) {
        if (data == 1) {
            return 1;
        } else {
          return factorial(data -1) * data;
        }
    }

    // 方法递归调用
    public static void  recursions(int e) {
        if (e > 1) {
            recursions(e - 1);
        }
        System.out.println("递归调用完成" + e);
    }



}